package zdream.control.test.world;

import org.junit.Test;

import java.util.concurrent.atomic.AtomicInteger;

import zdream.control.world.Ticker;

import static org.junit.Assert.*;

/**
 * @author Zdream
 * @date 2024-01-02
 * @since 0.0.1
 */
public class TickerCase {
	@Test
	public void testTicker() {
		Ticker ticker = new Ticker();

		assertEquals(1000f / 60, ticker.maxTickSecondsPerFrame, 1); // bias < 1ms
		assertEquals(1000f / 250, ticker.minTickSecondsPerFrame, 0.1); // bias < 1ms

		AtomicInteger counter = new AtomicInteger(0);
		ticker.everyTick = counter::incrementAndGet;

		ticker.runFrame(1f / 60);
		assertEquals(1, counter.get()); // assert speed one world tick
		assertEquals(1f / 60, ticker.delta, 0);
		assertEquals(0, ticker.lastActiveTime);
		assertEquals(0, ticker.lastWorldTime);
		assertEquals(0, ticker.worldTimeWhenFrameStart);
		assertEquals(0, ticker.activeTimeWhenFrameStart);
		assertEquals(1000 / 60, ticker.activeTime);
		assertEquals(1000 / 60, ticker.worldTime);
		assertEquals(1000 / 60, ticker.activeTimeWhenFrameFinished);
		assertEquals(1000 / 60, ticker.worldTimeWhenFrameFinished);
		assertEquals(1000 / 60, ticker.lDuration);
		assertEquals(1f / 60, ticker.duration, 0.001);
		assertEquals(0.016, ticker.duration, 0.000001); // rounded to three decimal places
		assertEquals(1f / 60 - 0.016, ticker.lastFrameRemain, 0.000001);
		counter.set(0);

		ticker.runFrame(0.025f); // 0.025 = 0.016 + 0.009
		assertEquals(2, counter.get());
		assertEquals(0.025f, ticker.delta, 0);
		assertEquals(32, ticker.lastActiveTime);
		assertEquals(32, ticker.lastWorldTime);
		assertEquals(16, ticker.worldTimeWhenFrameStart);
		assertEquals(16, ticker.activeTimeWhenFrameStart);
		assertEquals(41, ticker.activeTime); // 16 + 25 = 41
		assertEquals(41, ticker.worldTime);
		assertEquals(41, ticker.activeTimeWhenFrameFinished);
		assertEquals(41, ticker.worldTimeWhenFrameFinished);
		// the first tick is 0.016s, the last tick is 0.009s
		assertEquals(9, ticker.lDuration);
		assertEquals(0.009, ticker.duration, 0.001);
		assertTrue(ticker.lastFrameRemain < 0.001);
		assertTrue(ticker.lastFrameRemain > 0);
		// 0.025s 整 0.001, 所以计算后 lastFrameRemain 是不变的
		assertEquals(1f / 60 - 0.016, ticker.lastFrameRemain, 0.000001);
		counter.set(0);

		ticker.runFrame(0.019f); // 0.019 = 0.016 + 0.003, but 0.003 < 0.004 (minTickPerFrame)
		assertEquals(1, counter.get());
		assertEquals(0.019f, ticker.delta, 0);
		assertEquals(16, ticker.durationInFrame, 0);
		assertEquals(41, ticker.lastActiveTime);
		assertEquals(41, ticker.lastWorldTime);
		assertEquals(41, ticker.worldTimeWhenFrameStart);
		assertEquals(41, ticker.activeTimeWhenFrameStart);
		assertEquals(57, ticker.activeTime); // 41 + 16 = 57
		assertEquals(57, ticker.worldTime);
		assertEquals(57, ticker.activeTimeWhenFrameFinished);
		assertEquals(57, ticker.worldTimeWhenFrameFinished);
		// the first tick is 0.016s, the last tick is 0.009s
		assertEquals(16, ticker.lDuration);
		assertEquals(0.016, ticker.duration, 0.001);
		assertTrue(ticker.lastFrameRemain > 0);
		// 超出的 0.003 都加到 lastFrameRemain 中
		assertEquals(1f / 60 - 0.016 + 0.003, ticker.lastFrameRemain, 0.000001);
	}
}
